package UMC.Data;


import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.*;

public class ProviderConfiguration {
    private final HashSet<Provider> _config;

    private static final Map<String, ProviderConfiguration> configuration;

    static {
        configuration = new HashMap<>();
    }

    public ProviderConfiguration() {
        _config = new HashSet<>();
    }

    public ProviderConfiguration(InputStream inputStream) {
        _config = new HashSet<>();
        Document document = null;
        try {
            document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);
            inputStream.close();
        } catch (SAXException | IOException | ParserConfigurationException e) {
            e.printStackTrace();
        }
        if (document != null) {

            NodeList bookList = document.getElementsByTagName("add");

            for (int i = 0; i < bookList.getLength(); i++) {
                org.w3c.dom.Node node = bookList.item(i);
                Provider provider = new Provider(node);
                _config.add(provider);
            }
        }


    }

    public int size() {
        return _config.size();
    }

    public boolean containsKey(String name) {
        for (Provider provider : _config) {
            if (provider.name().equals(name)) {
                return true;
            }
        }
        return false;
    }

    public void put(Provider provider) {

        Provider provider1 = _config.stream().filter(r -> provider.name().equals(r.name())).findFirst().orElse(null);// r.name().)
        if (provider1 != null) {
            _config.remove(provider1);
        }
        this._config.add(provider);
    }

    public Provider get(String name) {
        for (Provider provider : _config) {
            if (provider.name().equals(name)) {
                return provider;
            }
        }
        return null;
    }

    public static void clear() {
        configuration.clear();
    }

    public static ProviderConfiguration configuration(String name) {
        if (configuration.containsKey(name)) {
            return configuration.get(name);
        } else {
            try {
                String filename = Utility.mapPath("UMC/" + name + ".xml");
                File file = new File(filename);
                if (!file.getParentFile().exists()) {
                    file.getParentFile().mkdir();
                }
                FileInputStream inputStream = new FileInputStream(filename);
                ProviderConfiguration providerConfiguration = new ProviderConfiguration(inputStream);
                configuration.put(name, providerConfiguration);
                return providerConfiguration;
            } catch (FileNotFoundException e) {
                //  e.printStackTrace();
            }
        }
        return null;
    }

    public static void configuration(String name, ProviderConfiguration configur) {
        configuration.put(name, configur);
        String filename = Utility.mapPath("UMC/" + name + ".xml");
        try {
            Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

            Element rootElement = document.createElement("umc");
            document.appendChild(rootElement);
            Element emp = document.createElement("providers");
            rootElement.appendChild(emp);
            for (Provider provider : configur._config) {

                Element add = document.createElement("add");
                add.setAttribute("name", provider.name());
                add.setAttribute("type", provider.type());

                for (Map.Entry<String, String> attr : provider.attributes().entrySet()) {
                    add.setAttribute(attr.getKey(), attr.getValue());
                }
                emp.appendChild(add);
            }
            TransformerFactory Transformer_Factory = TransformerFactory.newInstance();
            Transformer New_Transformer = Transformer_Factory.newTransformer();
            New_Transformer.setOutputProperty(OutputKeys.INDENT, "yes");

            DOMSource Source_XML = new DOMSource(document);
            StreamResult Result_XML = new StreamResult(filename);
            New_Transformer.transform(Source_XML, Result_XML);

        } catch (ParserConfigurationException | TransformerException e) {
            throw new RuntimeException(e);
        }

    }
}
